package com.duanjw.java.ticket;

import java.util.concurrent.TimeUnit;

/**
 * 使用synchronized实现同步
 *
 * 是一个可重入锁
 *
 * java中每一个对象都有一个monitor对象，监视器
 * <p>
 * 线程需要占有这个对象时，先看monitor计数器是不是0，
 * 如果是0表示还没有线程占有，可以占用对象，并且对象的monitor+1；
 * 如果不为0，表示该对象已被其他线程占有。
 * 当线程释放占有权的时候，monitor-1
 * <p>
 * <p>
 * ## 查看线程状态
 * 1. 可以在终端使用`jconsole`查看线程状态，可以看到一个线程是`TIMED_WAITING`状态，其他四个线程是`BLOCKED`
 * 2. 使用jstack [pid]
 * <p>
 * ## 反编译
 * javap -v [className]
 *
 * 1. 代码块用`monitorenter（锁入口）`和`monitorexit（锁出口）`加锁
 * 2. 方法用`ACC_SYNCHRONIZED`加锁
 *
 * JDK1.6之前用重量锁，性能不好，JDK1.6之后加入了偏向锁、轻量级锁
 * 锁状态有以下几个，等级逐渐递增：
 *  无锁：没有加锁
 *  偏向锁：在对象第一次被线程占有的时候，设置偏向锁为1，设置锁标志为01，设置线程号。当其他线程访问的时候。
 *         一般会被首次占用的线程获取次数多。适用于竞争不激烈的时候。竞争失败->转移到轻量级锁
 *  轻量级锁：适用于线程有交替。互斥性不是很强，竞争失败 -> 转移到重量级锁
 *  重量级锁：强互斥，等待时间长
 *
 *  自旋锁：竞争失败的时候，不马上等级，而是执行几次空循环
 *  锁消除：JIT在编译的时候把不必要的锁去掉
 *
 * 一个对象实例包含：对象头、实例变量、填充数据
 */
public class SynchroDemo {
    /**
     * 用synchronized修饰对象
     */
    public void accessResources1() {
        synchronized (this) {
            try {
                TimeUnit.SECONDS.sleep(200);
                System.out.println(Thread.currentThread().getName() + " is running");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 用synchronized修饰类
     */
    public void accessResources4() {
        synchronized (SynchroDemo.class) {
            try {
                TimeUnit.SECONDS.sleep(200);
                System.out.println(Thread.currentThread().getName() + " is running");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static synchronized void accessResources2() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SynchroDemo synchroDemo = new SynchroDemo();
        for (int i = 0; i < 5; i++) {
            new Thread(synchroDemo::accessResources1).start();
        }
    }
}
